package pl.edu.mimuw.irs.rcp.controller.part;

import java.lang.reflect.Constructor;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.Shape;
import org.eclipse.draw2d.Triangle;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.gef.EditPolicy;
import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.RGB;

import pl.edu.mimuw.irs.core.model.petrinet.Arc;
import pl.edu.mimuw.irs.core.model.petrinet.INode;
import pl.edu.mimuw.irs.core.util.Position;
import pl.edu.mimuw.irs.rcp.controller.policy.NodeComponentEditPolicy;
import pl.edu.mimuw.irs.rcp.controller.policy.WorkflowXYLayoutEditPolicy;
import pl.edu.mimuw.irs.rcp.view.figure.FigureWrapper;
import pl.edu.mimuw.irs.rcp.view.figure.IRSPlaceShape;
import pl.edu.mimuw.irs.rcp.view.figure.IRSTransitionShape;
import pl.edu.mimuw.irs.rcp.view.figure.PlaceShape;
import pl.edu.mimuw.irs.rcp.view.figure.TGPlaceShape;
import pl.edu.mimuw.irs.rcp.view.figure.TGTransitionShape;
import pl.edu.mimuw.irs.rcp.view.figure.TransitionShape;

/**
 * @author Jakub Rauch
 * Created on: 2009-05-27
 */
public abstract class AbstractNodeEditPart extends AbstractGraphicalEditPart implements INodeEditPart {
	
	// *** Attributes

	// *** Methods

	protected abstract NodeShape getNodeShape();
	
	@Override
	protected IFigure createFigure() {
		INode node = (INode)getModel();
		return getNodeShape().getShape(node.getPosition());
	}
	
	@Override
	public void activate() {
		super.activate();
	}
	@Override
	public void deactivate() {
		super.deactivate();
	}

	protected void refreshVisuals() {
		
		FigureWrapper wrapper = (FigureWrapper)getFigure();
		INode node = (INode)getModel();
		
		Label label;
		wrapper.setLineWidth(1);
		label = new Label(node.getId());
		Font placeFont = new Font(null, "Arial", 8, SWT.NORMAL);

		label.setFont(placeFont);
		label.setTextAlignment(PositionConstants.CENTER);
        label.setTextPlacement(PositionConstants.SOUTH);
		label.setBounds(wrapper.getBounds().crop(IFigure.NO_INSETS));
		wrapper.setLabel(label);
		
		super.refreshVisuals();
	}
	
	public INode getNode() {
		return (INode)getModel();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected List getModelChildren() {
		//return ((IRSNodeInterface)getModel()).getChildren();
		return super.getModelChildren();
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected List getModelSourceConnections() {
		Set<Arc> allArcs = getNode().getOutgoingArcs();
		List<Arc> visibleArcs = new LinkedList<Arc>();
		for (Arc arc : allArcs) {
			visibleArcs.add(arc);
		}
		
		return visibleArcs;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	protected List getModelTargetConnections() {
		Set<Arc> allArcs = getNode().getIncomingArcs();
		List<Arc> visibleArcs = new LinkedList<Arc>();
		for (Arc arc : allArcs) {
			visibleArcs.add(arc);
		}
		
		return visibleArcs;
	}

	@Override
	public void moveTo(Rectangle newBounds) {
		getNode().setPosition(new Position(newBounds.x, newBounds.y));
		// TODO powinno by� przez listenera i zrobi� w IRS rozmiar
		getFigure().setBounds(newBounds);
	}
	
	@Override
	public boolean isSelectable() {
		return true;
	}
	
	@Override
	protected void createEditPolicies() {
		installEditPolicy(EditPolicy.LAYOUT_ROLE, new WorkflowXYLayoutEditPolicy());
		installEditPolicy(EditPolicy.COMPONENT_ROLE, new NodeComponentEditPolicy());
	}
	
	// *** Enums
	
	public enum NodeShape {
		IRSPLACE(IRSPlaceShape.class, 40, 40),
		RESOURCE(IRSPlaceShape.class, 40, 40),
		IRSTRANSITION(IRSTransitionShape.class, 40, 40),
		ACTIVITY(IRSTransitionShape.class, 40, 40),
		PLACE(PlaceShape.class, 30, 30),
		TRANSITION(TransitionShape.class, 30, 30),
		TGPLACE(TGPlaceShape.class, 30, 30),
		TGTRANSITION(TGTransitionShape.class, 30, 30);
		
		private Class<? extends Shape> shape;
		private int width;
		private int height;
		public int getWidth() {
			return width;
		}
		public int getHeight() {
			return height;
		}
		
		NodeShape (Class<? extends Shape> shape, int width, int height) {
			this.shape = shape;
			this.width = width;
			this.height = height;
		}
		
		public FigureWrapper getShape(Position position) {
			Shape shapeInstance;
			FigureWrapper wrapper;
			try {
				Constructor<? extends Shape> constructor = shape.getConstructor();
				shapeInstance = constructor.newInstance();
				shapeInstance.setBounds(new Rectangle(position.getX(), position.getY(), width, height));
				wrapper = new FigureWrapper(shapeInstance);
			} catch (Exception e) {
				shapeInstance = new Triangle();
				shapeInstance.setBounds(new Rectangle(position.getX(), position.getY(), width, height));
				shapeInstance.setBackgroundColor(new Color(null, new RGB(255, 0, 0)));
				e.printStackTrace();// FIXME - powinien by� logger
				wrapper = new FigureWrapper(shapeInstance);
			}
			return wrapper;
		}
	}
}
